﻿/**
 * @file SimpleFtl.h
 * @brief 简易FTL（Flash Translation Layer）仿真模块，负责主机命令与NAND操作的协调。
 */
#ifndef __SimpleFtl_h__
#define __SimpleFtl_h__

#include "boost/lockfree/queue.hpp"
#include "Buffer/Hal/BufferHal.h"
#include "HostComm/CustomProtocol/CustomProtocolHal.h"
#include "Nand/Hal/NandHal.h"
#include "Translation.h"

/**
 * @class SimpleFtl
 * @brief 简易FTL仿真类，实现主机协议与NAND命令的转换与调度。
 * @details 继承CustomProtocolHal::TransferCommandListener和NandHal::CommandListener，处理主机命令、NAND读写、擦除等事件。
 */
class SimpleFtl : public CustomProtocolHal::TransferCommandListener, public NandHal::CommandListener
{
private:
    /**
     * @enum State
     * @brief FTL处理状态枚举。
     */
    enum State
    {
        PROCESSING, /**< 正在处理命令 */
        IDLE        /**< 空闲状态 */
    };

    /**
     * @struct Event
     * @brief FTL事件结构体，描述主机命令、传输完成、NAND命令完成等事件。
     */
    struct Event
    {
        /**
         * @enum Type
         * @brief 事件类型枚举。
         */
        enum class Type
        {
            CustomProtocolCommand, /**< 主机协议命令事件 */
            TransferCompleted,     /**< 数据传输完成事件 */
            NandCommandCompleted   /**< NAND命令完成事件 */
        };

        /**
         * @union Params
         * @brief 事件参数联合体。
         */
        union Params
        {
            CustomProtocolCommand *CustomProtocolCommand;           /**< 主机协议命令指针 */
            CustomProtocolHal::TransferCommandDesc TransferCommand; /**< 传输命令描述 */
            NandHal::CommandDesc NandCommand;                       /**< NAND命令描述 */
        };

        Type EventType;     /**< 事件类型 */
        Params EventParams; /**< 事件参数 */
    };

    static constexpr U8 MAX_PROCESSED_BLOCKS_PER_COMMAND{8}; /**< 单次命令最大处理块数 */

public:
    /**
     * @brief 构造函数。
     */
    SimpleFtl();

    /**
     * @brief 设置主机协议处理模块。
     * @param customProtocolHal 协议处理模块指针
     */
    void SetProtocol(CustomProtocolHal *customProtocolHal);
    /**
     * @brief 设置NAND硬件抽象层。
     * @param nandHal NAND硬件抽象层指针
     */
    void SetNandHal(NandHal *nandHal);
    /**
     * @brief 设置缓冲区管理器。
     * @param bufferHal 缓冲区管理器指针
     */
    void SetBufferHal(BufferHal *bufferHal);
    /**
     * @brief FTL主循环入口。
     */
    void operator()();

    /**
     * @brief 提交主机协议命令。
     * @param command 主机协议命令指针
     */
    void SubmitCustomProtocolCommand(CustomProtocolCommand *command);
    /**
     * @brief 传输命令完成回调。
     * @param command 传输命令描述
     */
    virtual void HandleCommandCompleted(const CustomProtocolHal::TransferCommandDesc &command);
    /**
     * @brief NAND命令完成回调。
     * @param command NAND命令描述
     */
    virtual void HandleCommandCompleted(const NandHal::CommandDesc &command);

    /**
     * @brief 检查是否正在处理命令。
     * @return 是否正在处理
     */
    bool IsProcessingCommand();

private:
    /**
     * @brief 处理事件队列。
     */
    void ProcessEvent();
    /**
     * @brief 读取下一个LBA区间。
     */
    void ReadNextLbas();
    /**
     * @brief 数据传出（主机->缓冲区）。
     * @param buffer 缓冲区
     * @param bufferOffset 缓冲区偏移
     * @param commandOffset 命令偏移
     * @param sectorCount 扇区数
     */
    void TransferOut(const Buffer &buffer, const tSectorOffset &bufferOffset, const tSectorOffset &commandOffset, const tSectorCount &sectorCount);
    /**
     * @brief 读取NAND页。
     * @param nandAddress NAND地址
     * @param outBuffer 输出缓冲区
     * @param descSectorIndex 描述扇区索引
     */
    void ReadPage(const NandHal::NandAddress &nandAddress, const Buffer &outBuffer, const tSectorOffset &descSectorIndex);

    /**
     * @brief 新写命令处理。
     */
    void OnNewWriteCommand();
    /**
     * @brief NAND读和传输完成处理。
     */
    void OnNandReadAndTransferCompleted();
    /**
     * @brief NAND擦除完成处理。
     */
    void OnNandEraseCompleted();
    /**
     * @brief 判断两个地址是否属于同一块。
     * @param nandAddress1 地址1
     * @param nandAddress2 地址2
     * @return 是否同块
     */
    bool IsSameBlock(const NandHal::NandAddress &nandAddress1, const NandHal::NandAddress &nandAddress2);
    /**
     * @brief 判断地址是否为新块。
     * @param nandAddress NAND地址
     * @return 是否新块
     */
    bool IsNewBlock(const NandHal::NandAddress &nandAddress);
    /**
     * @brief 获取块索引。
     * @param nandAddress NAND地址
     * @return 块索引
     */
    U32 GetBlockIndex(const NandHal::NandAddress &nandAddress);
    /**
     * @brief 获取子缓冲区。
     * @param blockIndex 块索引
     * @param nandAddress NAND地址
     * @return 子缓冲区
     */
    Buffer GetSubBuffer(const U32 &blockIndex, const NandHal::NandAddress &nandAddress);

    /**
     * @brief 读取头部页。
     * @param writingStartingPage 写入起始页地址
     * @param blockIndex 块索引
     */
    void ReadHeadPages(const NandHal::NandAddress &writingStartingPage, const U32 &blockIndex);
    /**
     * @brief 读取尾部页。
     * @param writingEndingPage 写入结束页地址
     * @param blockIndex 块索引
     */
    void ReadTailPages(const NandHal::NandAddress &writingEndingPage, const U32 &blockIndex);
    /**
     * @brief 数据传入（缓冲区->主机）。
     * @param buffer 缓冲区
     * @param bufferOffset 缓冲区偏移
     * @param commandOffset 命令偏移
     * @param sectorCount 扇区数
     */
    void TransferIn(const Buffer &buffer, const tSectorOffset &bufferOffset, const tSectorOffset &commandOffset, const tSectorCount &sectorCount);
    /**
     * @brief 擦除指定块。
     * @param nandAddress NAND地址
     */
    void EraseBlock(const NandHal::NandAddress &nandAddress);
    /**
     * @brief 写NAND页。
     * @param nandAddress NAND地址
     * @param outBuffer 输出缓冲区
     */
    void WritePage(const NandHal::NandAddress &nandAddress, const Buffer &outBuffer);

    /**
     * @brief 设置扇区信息。
     * @param sectorInfo 扇区信息结构体
     * @return 是否设置成功
     */
    bool SetSectorInfo(const SectorInfo &sectorInfo);

    /**
     * @brief 新主机协议命令处理。
     * @param command 主机协议命令指针
     */
    void OnNewCustomProtocolCommand(CustomProtocolCommand *command);
    /**
     * @brief 传输命令完成处理。
     * @param command 传输命令描述
     */
    void OnTransferCommandCompleted(const CustomProtocolHal::TransferCommandDesc &command);
    /**
     * @brief NAND命令完成处理。
     * @param command NAND命令描述
     */
    void OnNandCommandCompleted(const NandHal::CommandDesc &command);

    /**
     * @brief 提交命令响应。
     */
    void SubmitResponse();

private:
    NandHal *_NandHal;                     /**< NAND硬件抽象层指针 */
    BufferHal *_BufferHal;                 /**< 缓冲区管理器指针 */
    CustomProtocolHal *_CustomProtocolHal; /**< 主机协议处理模块指针 */
    U32 _TotalSectors;                     /**< 总扇区数 */
    U8 _SectorsPerPage;                    /**< 每页扇区数 */
    U8 _SectorsPerSegment;                 /**< 每段扇区数 */
    U32 _PagesPerBlock;                    /**< 每块页数 */

    Buffer _ProcessingBlockBuffers[MAX_PROCESSED_BLOCKS_PER_COMMAND];         /**< 当前处理块缓冲区 */
    NandHal::NandAddress _ProcessingBlocks[MAX_PROCESSED_BLOCKS_PER_COMMAND]; /**< 当前处理块地址 */
    U32 _ProcessingBlockCount;                                                /**< 当前处理块数量 */

    CustomProtocolCommand *_ProcessingCommand; /**< 当前处理命令指针 */
    tSectorOffset _ProcessedSectorOffset;      /**< 已处理扇区偏移 */
    U32 _RemainingSectorCount;                 /**< 剩余待处理扇区数 */
    U32 _CurrentLba;                           /**< 当前LBA */
    U32 _PendingTransferCommandCount;          /**< 待完成传输命令数 */
    U32 _PendingNandCommandCount;              /**< 待完成NAND命令数 */

    bip::interprocess_mutex *_Mutex;                            /**< 互斥锁指针 */
    std::unique_ptr<boost::lockfree::queue<Event>> _EventQueue; /**< 事件队列 */
};

#endif